<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript">
      // 源数据
      let person = {
        name: '张三',
        age: 18,
      };
      // 模拟Vue2中实现响应式
      //#region
      // 模拟vue2中实现响应式
      /* let p = {};
      Object.defineProperty(p, 'name', {
        configurable: true, //可配置的，这样就可以delete删除了
        get() {
          //有人读取name时调用
          return person.name;
        },
        set(value) {
          //有人修改name时调用
          console.log('有人修改了name属性，我发现了，我要去更新界面');
          person.name = value;
        },
      });
      Object.defineProperty(p, 'age', {
        get() {
          //有人读取age时调用
          return person.age;
        },
        set(value) {
          //有人修改age时调用
          console.log('有人修改了age属性，我发现了，我要去更新界面');
          person.age = value;
        },
      }); */
      //#endregion
      // 模拟vue3中实现响应式
      //#region
      // window.Proxy
      // {}什么都不改，传递一个空对象占位
      const p = new Proxy(person, {
        // 增删改查
        //有人读取p的某个属性时调用
        get(target, propName) {
          console.log(`有人读取了p身上的${propName}属性`, target, propName);
          // return target[propName];
          return Reflect.get(target, propName);
        },
        // 有人修改p的某个属性，或者给p追加某个属性时调用
        set(target, propName, value) {
          console.log(target, propName, value);
          console.log(`有人修改了p身上的${propName}属性，我要去更新界面了！`);
          // target[propName] = value;
          Reflect.set(target, propName, value);
        },
        // 有人删除p的某个属性时调用
        deleteProperty(target, propName) {
          console.log(`有人删除了p身上的${propName}属性，我要去更新界面了`);
          // return delete target[propName];
          return Reflect.deleteProperty(target, propName);
        },
      });
      //#endregion

      let obj = {
        a: 1,
        b: 2,
      };
      // 通过Object.defineProperty去操作
      //#region
      /*  Object.defineProperty(obj, 'c', {
        get() {
          return 100;
        },
      });
      // 不是覆盖前面的值，而是重复定义 报错 改用Reflect
      Object.defineProperty(obj, 'c', {
        get() {
          return 101;
        },
      }); */
      //#endregion
      const x1 = Reflect.defineProperty(obj, 'c', {
        get() {
          return 100;
        },
      });
      console.log('x1', x1);
      // 不是覆盖前面的值，而是重复定义 报错 改用Reflect
      const x2 = Reflect.defineProperty(obj, 'c', {
        get() {
          return 101;
        },
      });
      if (x2) {
        console.log('某某某操作成功了');
      } else {
        console.log('某某某操作失败了');
      }
      console.log('x2', x2);
    </script>
  </body>
</html>
